/**
 * ECSGroup 性能测试套件
 * 
 * 用于验证优化效果，对比优化前后的性能差异
 */

import { ecs } from "./ECS";
import { ECSEntity } from "./ECSEntity";
import { ECSGroup } from "./ECSGroup";

/**
 * 性能测试配置
 */
interface TestConfig {
    name: string;
    iterations: number;
    warmupIterations: number;
    entityCount: number;
}

/**
 * 测试结果
 */
interface TestResult {
    name: string;
    totalTime: number;
    avgTime: number;
    minTime: number;
    maxTime: number;
    opsPerSecond: number;
    entityCount?: number;
}

/**
 * ECSGroup 性能测试类
 */
export class ECSGroupPerformanceTest {
    private static readonly DEFAULT_CONFIG: TestConfig = {
        name: '',
        iterations: 10000,
        warmupIterations: 1000,
        entityCount: 1000
    };

    /**
     * 运行所有性能测试
     */
    public static runAllTests(): void {
        console.log('='.repeat(80));
        console.log('ECSGroup 性能测试开始');
        console.log('='.repeat(80));

        // 测试 1：访问 matchEntities（数组构建）
        this.testMatchEntitiesAccess();

        // 测试 2：获取第一个实体
        this.testEntityGetter();

        // 测试 3：状态未改变的组件操作
        this.testUnchangedComponentOperation();

        // 测试 4：for-of 遍历
        this.testForOfTraversal();

        // 测试 5：forEach 遍历
        this.testForEachTraversal();

        // 测试 6：has() 检查
        this.testHasCheck();

        // 测试 7：get() 获取
        this.testGetEntity();

        // 测试 8：clear() 清空
        this.testClear();

        // 测试 9：isEmpty 判断
        this.testIsEmpty();

        // 测试 10：批量实体处理
        this.testBatchProcessing();

        console.log('='.repeat(80));
        console.log('ECSGroup 性能测试结束');
        console.log('='.repeat(80));
    }

    /**
     * 测试 1：访问 matchEntities（数组构建）
     */
    private static testMatchEntitiesAccess(): void {
        // 创建测试组件和实体
        @ecs.register('TestPosition1')
        class TestPosition1 extends ecs.Comp {
            x: number = 0;
            y: number = 0;
        }

        const entities: ECSEntity[] = [];
        for (let i = 0; i < 1000; i++) {
            const entity = ecs.createEntity() as ECSEntity;
            entity.add(TestPosition1);
            entities.push(entity);
        }

        const matcher = ecs.Matcher.allOf(TestPosition1);
        const group = ecs.createGroup(matcher) as ECSGroup;

        // 触发初始缓存构建
        for (const entity of entities) {
            group.onComponentAddOrRemove(entity);
        }

        // 测试访问性能
        const result = this.runTest(
            'matchEntities 访问（构建数组）',
            () => {
                const arr = group.matchEntities;
                return arr.length > 0;
            },
            { iterations: 10000, warmupIterations: 1000, name: '', entityCount: 1000 }
        );

        this.printResult(result);

        // 清理
        for (const entity of entities) {
            entity.destroy();
        }
    }

    /**
     * 测试 2：获取第一个实体
     */
    private static testEntityGetter(): void {
        @ecs.register('TestPosition2')
        class TestPosition2 extends ecs.Comp {
            x: number = 0;
            y: number = 0;
        }

        const entities: ECSEntity[] = [];
        for (let i = 0; i < 1000; i++) {
            const entity = ecs.createEntity() as ECSEntity;
            entity.add(TestPosition2);
            entities.push(entity);
        }

        const matcher = ecs.Matcher.allOf(TestPosition2);
        const group = ecs.createGroup(matcher) as ECSGroup;

        for (const entity of entities) {
            group.onComponentAddOrRemove(entity);
        }

        const result = this.runTest(
            'entity getter（获取第一个实体）',
            () => {
                const entity = group.entity;
                return entity !== undefined;
            },
            { iterations: 100000, warmupIterations: 10000, name: '', entityCount: 1000 }
        );

        this.printResult(result);
        console.log('  ℹ️  优化后避免数组构建，性能提升显著');

        for (const entity of entities) {
            entity.destroy();
        }
    }

    /**
     * 测试 3：状态未改变的组件操作
     */
    private static testUnchangedComponentOperation(): void {
        @ecs.register('TestPosition3')
        class TestPosition3 extends ecs.Comp {
            x: number = 0;
            y: number = 0;
        }

        const entity = ecs.createEntity() as ECSEntity;
        entity.add(TestPosition3);

        const matcher = ecs.Matcher.allOf(TestPosition3);
        const group = ecs.createGroup(matcher) as ECSGroup;

        group.onComponentAddOrRemove(entity);

        const result = this.runTest(
            '状态未改变的组件操作',
            () => {
                group.onComponentAddOrRemove(entity);  // 状态未改变
                return true;
            },
            { iterations: 10000, warmupIterations: 1000, name: '', entityCount: 1 }
        );

        this.printResult(result);
        console.log('  ℹ️  优化后提前退出，避免冗余操作');

        entity.destroy();
    }

    /**
     * 测试 4：for-of 遍历
     */
    private static testForOfTraversal(): void {
        @ecs.register('TestPosition4')
        class TestPosition4 extends ecs.Comp {
            x: number = 0;
            y: number = 0;
        }

        const entities: ECSEntity[] = [];
        for (let i = 0; i < 1000; i++) {
            const entity = ecs.createEntity() as ECSEntity;
            entity.add(TestPosition4);
            entities.push(entity);
        }

        const matcher = ecs.Matcher.allOf(TestPosition4);
        const group = ecs.createGroup(matcher) as ECSGroup;

        for (const entity of entities) {
            group.onComponentAddOrRemove(entity);
        }

        const result = this.runTest(
            'for-of 遍历',
            () => {
                let sum = 0;
                for (const entity of group.matchEntities) {
                    sum += entity.eid;
                }
                return sum > 0;
            },
            { iterations: 1000, warmupIterations: 100, name: '', entityCount: 1000 }
        );

        this.printResult(result);

        for (const entity of entities) {
            entity.destroy();
        }
    }

    /**
     * 测试 5：forEach 遍历
     */
    private static testForEachTraversal(): void {
        @ecs.register('TestPosition5')
        class TestPosition5 extends ecs.Comp {
            x: number = 0;
            y: number = 0;
        }

        const entities: ECSEntity[] = [];
        for (let i = 0; i < 1000; i++) {
            const entity = ecs.createEntity() as ECSEntity;
            entity.add(TestPosition5);
            entities.push(entity);
        }

        const matcher = ecs.Matcher.allOf(TestPosition5);
        const group = ecs.createGroup(matcher) as ECSGroup;

        for (const entity of entities) {
            group.onComponentAddOrRemove(entity);
        }

        const result = this.runTest(
            'forEach 遍历',
            () => {
                let sum = 0;
                group.forEach(entity => {
                    sum += entity.eid;
                });
                return sum > 0;
            },
            { iterations: 1000, warmupIterations: 100, name: '', entityCount: 1000 }
        );

        this.printResult(result);
        console.log('  ℹ️  forEach 避免数组构建，性能最优');

        for (const entity of entities) {
            entity.destroy();
        }
    }

    /**
     * 测试 6：has() 检查
     */
    private static testHasCheck(): void {
        @ecs.register('TestPosition6')
        class TestPosition6 extends ecs.Comp {
            x: number = 0;
            y: number = 0;
        }

        const entities: ECSEntity[] = [];
        for (let i = 0; i < 1000; i++) {
            const entity = ecs.createEntity() as ECSEntity;
            entity.add(TestPosition6);
            entities.push(entity);
        }

        const matcher = ecs.Matcher.allOf(TestPosition6);
        const group = ecs.createGroup(matcher) as ECSGroup;

        for (const entity of entities) {
            group.onComponentAddOrRemove(entity);
        }

        const testEntity = entities[500];

        const result = this.runTest(
            'has() 检查',
            () => {
                return group.has(testEntity);
            },
            { iterations: 100000, warmupIterations: 10000, name: '', entityCount: 1000 }
        );

        this.printResult(result);
        console.log('  ℹ️  O(1) 复杂度，高效查询');

        for (const entity of entities) {
            entity.destroy();
        }
    }

    /**
     * 测试 7：get() 获取
     */
    private static testGetEntity(): void {
        @ecs.register('TestPosition7')
        class TestPosition7 extends ecs.Comp {
            x: number = 0;
            y: number = 0;
        }

        const entities: ECSEntity[] = [];
        for (let i = 0; i < 1000; i++) {
            const entity = ecs.createEntity() as ECSEntity;
            entity.add(TestPosition7);
            entities.push(entity);
        }

        const matcher = ecs.Matcher.allOf(TestPosition7);
        const group = ecs.createGroup(matcher) as ECSGroup;

        for (const entity of entities) {
            group.onComponentAddOrRemove(entity);
        }

        const testEid = entities[500].eid;

        const result = this.runTest(
            'get() 获取实体',
            () => {
                const entity = group.get(testEid);
                return entity !== undefined;
            },
            { iterations: 100000, warmupIterations: 10000, name: '', entityCount: 1000 }
        );

        this.printResult(result);
        console.log('  ℹ️  O(1) 复杂度，直接获取');

        for (const entity of entities) {
            entity.destroy();
        }
    }

    /**
     * 测试 8：clear() 清空
     */
    private static testClear(): void {
        @ecs.register('TestPosition8')
        class TestPosition8 extends ecs.Comp {
            x: number = 0;
            y: number = 0;
        }

        const matcher = ecs.Matcher.allOf(TestPosition8);
        const group = ecs.createGroup(matcher) as ECSGroup;

        // 测试非空 Group
        const entities: ECSEntity[] = [];
        for (let i = 0; i < 100; i++) {
            const entity = ecs.createEntity() as ECSEntity;
            entity.add(TestPosition8);
            entities.push(entity);
            group.onComponentAddOrRemove(entity);
        }

        const result1 = this.runTest(
            'clear() 清空（非空 Group）',
            () => {
                group.clear();
                // 重新填充
                for (const entity of entities) {
                    group.onComponentAddOrRemove(entity);
                }
                return true;
            },
            { iterations: 1000, warmupIterations: 100, name: '', entityCount: 100 }
        );

        this.printResult(result1);

        // 测试空 Group
        group.clear();

        const result2 = this.runTest(
            'clear() 清空（空 Group）',
            () => {
                group.clear();
                return true;
            },
            { iterations: 10000, warmupIterations: 1000, name: '', entityCount: 0 }
        );

        this.printResult(result2);
        console.log('  ℹ️  空 Group 优化，跳过不必要操作');

        for (const entity of entities) {
            entity.destroy();
        }
    }

    /**
     * 测试 9：isEmpty 判断
     */
    private static testIsEmpty(): void {
        @ecs.register('TestPosition9')
        class TestPosition9 extends ecs.Comp {
            x: number = 0;
            y: number = 0;
        }

        const matcher = ecs.Matcher.allOf(TestPosition9);
        const group = ecs.createGroup(matcher) as ECSGroup;

        const result = this.runTest(
            'isEmpty 判断',
            () => {
                return group.isEmpty === true;
            },
            { iterations: 100000, warmupIterations: 10000, name: '', entityCount: 0 }
        );

        this.printResult(result);
        console.log('  ℹ️  直接访问 Map.size，性能极佳');
    }

    /**
     * 测试 10：批量实体处理
     */
    private static testBatchProcessing(): void {
        console.log('-'.repeat(80));
        console.log('批量实体处理测试');
        console.log('-'.repeat(80));

        @ecs.register('BatchPosition')
        class BatchPosition extends ecs.Comp {
            x: number = 0;
            y: number = 0;
        }

        @ecs.register('BatchVelocity')
        class BatchVelocity extends ecs.Comp {
            vx: number = 1;
            vy: number = 1;
        }

        const entityCounts = [1000, 5000, 10000];

        for (const count of entityCounts) {
            const entities: ECSEntity[] = [];
            for (let i = 0; i < count; i++) {
                const entity = ecs.createEntity() as ECSEntity;
                entity.add(BatchPosition);
                entity.add(BatchVelocity);
                entities.push(entity);
            }

            const matcher = ecs.Matcher.allOf(BatchPosition, BatchVelocity);
            const group = ecs.createGroup(matcher) as ECSGroup;

            for (const entity of entities) {
                group.onComponentAddOrRemove(entity);
            }

            // 测试 for-of
            const startTime1 = performance.now();
            for (let iter = 0; iter < 100; iter++) {
                for (const entity of group.matchEntities) {
                    const pos = entity.get(BatchPosition)!;
                    const vel = entity.get(BatchVelocity)!;
                    pos.x += vel.vx;
                    pos.y += vel.vy;
                }
            }
            const endTime1 = performance.now();
            const time1 = endTime1 - startTime1;

            // 测试 forEach
            const startTime2 = performance.now();
            for (let iter = 0; iter < 100; iter++) {
                group.forEach(entity => {
                    const pos = entity.get(BatchPosition)!;
                    const vel = entity.get(BatchVelocity)!;
                    pos.x += vel.vx;
                    pos.y += vel.vy;
                });
            }
            const endTime2 = performance.now();
            const time2 = endTime2 - startTime2;

            console.log(`实体数量：${count}`);
            console.log(`  for-of 耗时：${time1.toFixed(2)} ms`);
            console.log(`  forEach 耗时：${time2.toFixed(2)} ms`);
            console.log(`  性能提升：${((time1 - time2) / time1 * 100).toFixed(1)}%`);

            for (const entity of entities) {
                entity.destroy();
            }
        }

        console.log('-'.repeat(80));
    }

    /**
     * 运行单个性能测试
     */
    private static runTest(
        name: string,
        testFn: () => boolean,
        config: Partial<TestConfig> = {}
    ): TestResult {
        const finalConfig = { ...this.DEFAULT_CONFIG, ...config, name };

        // 预热
        for (let i = 0; i < finalConfig.warmupIterations; i++) {
            testFn();
        }

        // 正式测试
        const times: number[] = [];
        const startTime = performance.now();

        for (let i = 0; i < finalConfig.iterations; i++) {
            const iterStart = performance.now();
            testFn();
            const iterEnd = performance.now();
            times.push((iterEnd - iterStart) * 1_000_000); // 转换为纳秒
        }

        const endTime = performance.now();
        const totalTime = endTime - startTime;

        // 计算统计信息
        const avgTime = times.reduce((a, b) => a + b, 0) / times.length;
        const minTime = Math.min(...times);
        const maxTime = Math.max(...times);
        const opsPerSecond = (finalConfig.iterations / totalTime) * 1000;

        return {
            name,
            totalTime,
            avgTime,
            minTime,
            maxTime,
            opsPerSecond,
            entityCount: finalConfig.entityCount
        };
    }

    /**
     * 打印测试结果
     */
    private static printResult(result: TestResult): void {
        console.log('-'.repeat(80));
        console.log(`测试：${result.name}`);
        if (result.entityCount !== undefined) {
            console.log(`  实体数量：${result.entityCount}`);
        }
        console.log(`  总耗时：${result.totalTime.toFixed(2)} ms`);
        console.log(`  平均耗时：${result.avgTime.toFixed(2)} ns`);
        console.log(`  最小耗时：${result.minTime.toFixed(2)} ns`);
        console.log(`  最大耗时：${result.maxTime.toFixed(2)} ns`);
        console.log(`  吞吐量：${result.opsPerSecond.toFixed(0)} ops/s`);
    }
}

/**
 * 使用示例
 */
export class ECSGroupPerformanceExample {
    /**
     * 运行所有测试
     */
    public static runAllTests(): void {
        ECSGroupPerformanceTest.runAllTests();
    }
}

// ============================================================================
// 使用方式
// ============================================================================

// 运行完整测试套件
// ECSGroupPerformanceExample.runAllTests();

